// import type { NitroFetchOptions } from 'nitropack'
// import type { FetchContext } from 'ofetch'
// import { Modal, message } from 'ant-design-vue'
// import AES from 'crypto-js/aes'
// import Utf8 from 'crypto-js/enc-utf8'
// import PadPkcs7 from 'crypto-js/pad-pkcs7'
// import ModeEcb from 'crypto-js/mode-ecb'
// import WordArray from 'crypto-js/lib-typedarrays'
// import { jwtDecode } from 'jwt-decode'
// import chalk from 'chalk'
// import { stringify } from 'superjson'
// import { nanoid } from 'nanoid'
// import type { NuxtError } from '#app'
// import { useUserStore } from '~/stores/user'

// export interface DataResponseWrapper<T = unknown> {
//   data: T
//   // 兼容新旧两版后端状态码的返回
//   status: number | { status: number }
//   encrypt?: boolean
//   msg?: string | null
// }

// // 登录/权限不足弹窗
// let isAuthErrorModalVisible = false
// export const showAuthErrorModal = (
//   type: 'token' | 'permission' = 'token',
//   message?: string
// ) => {
//   if (!isAuthErrorModalVisible) {
//     const route = useRoute()
//     const { $i18n, $localePath } = useNuxtApp()
//     const { t, locale } = $i18n
//     if (type === 'token') {
//       // token 类型的错误弹窗需清空用户信息
//       const userStore = useUserStore()
//       userStore.logout({ soft: true })
//     }
//     isAuthErrorModalVisible = true
//     Modal.confirm({
//       title:
//         message ||
//         (type === 'permission'
//           ? t('common.noPermissionData')
//           : t('common.tokenInvalid')),
//       okText:
//         type === 'permission'
//           ? t('common.noPermissionBtn')
//           : t('common.tokenInvalidLoginBtn'),
//       cancelText:
//         type === 'permission'
//           ? t('common.noPermissionCancelBtn')
//           : t('common.tokenInvalidBackToHomeBtn'),
//       keyboard: false,
//       closable: false,
//       maskClosable: false,
//       maskStyle:
//         type === 'permission'
//           ? {}
//           : {
//             backdropFilter: 'blur(16px)'
//           },
//       onOk: () => {
//         if (type === 'permission') {
//           if (
//             route.path.replace(new RegExp(`^/${locale.value}`), '') !==
//             '/pricing'
//           ) {
//             navigateTo($localePath('/pricing'))
//           }
//         } else {
//           if (
//             route.path.replace(new RegExp(`^/${locale.value}`), '') !== '/login'
//           ) {
//             navigateTo($localePath(`/login?redirect=${route.fullPath}`))
//           }
//         }
//       },
//       onCancel: () => {
//         if (type !== 'permission') {
//           if (
//             ['', '/', '/home'].includes(
//               route.path.replace(new RegExp(`^/${locale.value}`), '')
//             )
//           ) {
//             window.location.reload()
//           } else {
//             navigateTo($localePath('/'))
//           }
//         }
//       },
//       afterClose: () => {
//         isAuthErrorModalVisible = false
//       }
//     })
//   }
// }

// const httpErrorMessageKeyPrefix = 'httpErrorMessageKey'
// const isShowErrorCodeOnMessage = false
// const throwError = (
//   err: Partial<NuxtError>,
//   options?: {
//     hideToast?: boolean
//     noTracking?: boolean
//   }
// ) => {
//   const errorMessage = err.message ?? err.statusMessage
//   if (errorMessage) {
//     if (import.meta.server) {
//       console.dir(err, {
//         depth: null
//       })
//     } else {
//       if (!options?.hideToast) {
//         let apiCodeString: string | undefined
//         // 把 API 报错信息中 "xxx (#500)" 的 "(#500)" 抽取出来做样式处理
//         const foundApiCodeString = /\(#\w+\)$/gmu.exec(errorMessage)
//         if (foundApiCodeString !== null) {
//           apiCodeString = foundApiCodeString[0]
//         }
//         message.destroy(`${httpErrorMessageKeyPrefix}_${errorMessage}`)
//         message.error({
//           key: `${httpErrorMessageKeyPrefix}_${errorMessage}`,
//           content: isShowErrorCodeOnMessage
//             ? h('span', [
//               h(
//                 'span',
//                 apiCodeString
//                   ? errorMessage.replace(apiCodeString, '')
//                   : errorMessage
//               ),
//               h(
//                 'small',
//                 {
//                   style: {
//                     opacity: '0.5'
//                   }
//                 },
//                 apiCodeString ?? ''
//               )
//             ])
//             : apiCodeString
//               ? errorMessage.replace(apiCodeString, '')
//               : errorMessage
//         })
//       }
//       if (!options?.noTracking) {
//         // 发送埋点
//         const { sendEvent } = useTracking()
//         sendEvent({
//           rsCode: 'gn_network_error_log',
//           rsName: '网络错误日志',
//           eventCode: 'click',
//           eventContext: {
//             errorMsg: stringify(err)
//           }
//         })
//       }
//     }
//   }
//   throw createError(err)
// }

// // 将网络请求的上下文转换成日志存储的格式
// const transformContextToLog = (
//   context: Partial<FetchContext & { options: Parameters<typeof http>[0] }>
// ) => {
//   const request: Record<string, any> = {}
//   if (context.options) {
//     const { baseURL, path, method, headers, data, page } = context.options
//     request.baseURL = baseURL
//     request.path = path
//     request.method = method
//     request.headers = Object.fromEntries([...(headers as Headers)?.entries?.()])
//     request.data = data
//     request.page = page
//   }
//   const response: Record<string, any> = {}
//   if (context.response instanceof Response) {
//     response.headers = Object.fromEntries([
//       ...(context.response.headers as Headers)?.entries?.()
//     ])
//     response.status = context.response.status
//     response.statusText = context.response.statusText
//     response.data = context.response._data
//   }
//   return {
//     request,
//     response,
//     error: context.error
//   }
// }

// export const http = <
//   DataResponse,
//   DataRequest extends Record<string, any> = {},
// >(
//   options: NitroFetchOptions<string> & {
//     path: string
//     data?: DataRequest
//     page?: {
//       page?: any
//       pageSize?: any
//     }
//     // HIDE_TOAST = 不显示页面错误提示
//     silentError?: boolean | 'HIDE_TOAST'
//     rawResponse?: boolean
//   }
// ): Promise<DataResponse | never | undefined> => {
//   const config = useRuntimeConfig()
//   const { $i18n } = useNuxtApp()
//   const { t, locale, defaultLocale } = $i18n
//   const userStore = useUserStore()
//   options = options || {}
//   let { path } = options
//   if (!path) {
//     options.silentError !== true &&
//       throwError(
//         {
//           message: t('http.networkErrorMsg')
//         },
//         {
//           hideToast: options.silentError === 'HIDE_TOAST'
//         }
//       )
//   }
//   // 如果 path 传入相对路径
//   if (!/^https?:\/\//.test(path)) {
//     if (import.meta.client && import.meta.dev) {
//       // 开发环境下，浏览器发起的请求均接上 apiUrlProxyPrefix 前缀
//       // 使其匹配中框架配置的 proxy 路由，从而使用 node 进行转发
//       path = `${config.public.apiUrlProxyPrefix}/${path}`.replace(/\/\//g, '/')
//     } else {
//       // 服务器发起的请求 或 非开发环境的所有请求都直接使用 API 源
//       options.baseURL = config.public.apiUrlBase
//     }
//   }
//   if (options.method?.toLowerCase() === 'get') {
//     const payload: Record<string, any> = {}
//     if (options.data) {
//       Object.entries(options.data).forEach(
//         ([key, value]) => (payload[key] = value)
//       )
//     }
//     if (options.page) {
//       Object.entries(options.page).forEach(
//         ([key, value]) => (payload[key] = value)
//       )
//     }
//     options.query = payload
//   } else {
//     if (options.data instanceof FormData) {
//       options.body = options.data
//     } else {
//       const payload: Record<string, any> = {}
//       payload.data = options.data ?? {}
//       if (options.page) {
//         payload.page = options.page
//       }
//       options.body = payload
//     }
//   }
//   let devRequestId: string
//   return $fetch(path, {
//     // 请求重试
//     retry: 2,
//     // 请求重试间隔（毫秒）
//     retryDelay: 500,
//     // 超时（毫秒）
//     timeout: import.meta.server ? 20 * 1000 : 2 * 60 * 1000,
//     // 默认发送 post 请求
//     method: 'post',
//     onRequest({ options }) {
//       if (import.meta.server && import.meta.dev) {
//         devRequestId = nanoid(4)
//         console.log(
//           chalk.bgYellow(`💭 >> ${options.method}`),
//           chalk.blue(path),
//           chalk.gray(`#${devRequestId}`)
//         )
//         console.log(
//           chalk.bgMagenta('PAYLOAD'),
//           chalk.bgWhite.black(stringify(options.body ?? options.query))
//         )
//         console.time(chalk.gray(`${path} #${devRequestId} TIME`))
//       }
//       // 设置请求头
//       options.headers = {
//         // locale
//         [config.public.cookie.locale as string]: locale.value ?? defaultLocale,
//         // token
//         ...(options.credentials !== 'omit' && userStore.token?.length
//           ? {
//             [config.public.cookie.token as string]: userStore.token ?? ''
//           }
//           : {}),
//         ...options.headers
//       }
//     },
//     onResponse({ request, response, options: _options }) {
//       const options = _options as Parameters<typeof http>[0]
//       if (response.status === 200) {
//         if (import.meta.server && import.meta.dev) {
//           console.log(chalk.bgGreen(`💡 << RESPONSE ${response.status}`))
//           console.timeEnd(chalk.gray(`${path} #${devRequestId} TIME`))
//           console.log(
//             chalk.bgBlue('DATA'),
//             chalk.bgWhite.black(stringify(response._data))
//           )
//         }
//         const rawResponse = response._data as DataResponseWrapper<DataResponse>
//         // 如果设置了 rawResponse === true 或响应体为二进制的请求，不作处理直接返回原始响应
//         if (!options.rawResponse && !(rawResponse instanceof Blob)) {
//           if (
//             typeof (rawResponse.status as { status: number })?.status ===
//             'number'
//           ) {
//             // 兼容旧版后端的状态码
//             rawResponse.status = (
//               rawResponse.status as { status: number }
//             ).status
//           }
//           if (typeof rawResponse.status === 'number') {
//             if (rawResponse.status === 0) {
//               if (
//                 // @ts-ignore
//                 // rawResponse.encrypt
//                 rawResponse[
//                   ['t', 'p', 'y', 'r', 'c', 'n', 'e'].reverse().join('')
//                 ]
//               ) {
//                 // 处理加密的响应体数据
//                 try {
//                   const rawToken = userStore.token ?? ''
//                   if (rawToken) {
//                     const decodedToken = jwtDecode(rawToken) as {
//                       sub: string
//                       user_name: string
//                       orgId: string
//                     }
//                     const sigBytes = 16
//                     const key =
//                       `${decodedToken?.sub}${decodedToken?.user_name}${decodedToken?.orgId}`
//                         .padEnd(sigBytes, '0')
//                         .substring(0, sigBytes)
//                     const parsedData = AES.decrypt(
//                       rawResponse.data as string,
//                       WordArray.create(Utf8.parse(key).words, sigBytes),
//                       {
//                         mode: ModeEcb,
//                         padding: PadPkcs7
//                       }
//                     ).toString(Utf8)
//                     try {
//                       response._data = JSON.parse(parsedData)
//                     } catch {
//                       // 如果解析出来的结果是个非标准 json 数据，直接将结果赋值
//                       response._data = parsedData
//                     }
//                   } else {
//                     response._data = {}
//                   }
//                 } catch (e) {
//                   response._data = {}
//                   options.silentError !== true &&
//                     throwError(
//                       {
//                         data: transformContextToLog({
//                           request,
//                           response,
//                           options
//                         }),
//                         cause: {
//                           reason: 'onApiDecryptError',
//                           status: response.status
//                         },
//                         message: (e as Error)?.message
//                       },
//                       {
//                         hideToast: options.silentError === 'HIDE_TOAST'
//                       }
//                     )
//                 }
//               } else {
//                 response._data = rawResponse.data
//               }
//             } else {
//               if (import.meta.client) {
//                 if (String(rawResponse.status) === '401') {
//                   // 401 开头的错误代码，弹出权限不足弹窗
//                   showAuthErrorModal('permission')
//                 }
//                 if (String(rawResponse.status).startsWith('44')) {
//                   // 44x 开头的错误代码，弹出登录弹窗
//                   showAuthErrorModal('token')
//                 }
//               }
//               options.silentError !== true &&
//                 throwError(
//                   {
//                     data: transformContextToLog({
//                       request,
//                       response,
//                       options
//                     }),
//                     cause: {
//                       reason: 'onApiBusinessError',
//                       status: response.status,
//                       code: rawResponse.status,
//                       message: rawResponse.msg
//                     },
//                     statusCode: response.status,
//                     message: `${rawResponse.msg as string} (#${
//                       rawResponse.status
//                     })`
//                   },
//                   {
//                     hideToast: options.silentError === 'HIDE_TOAST',
//                     // 只有 5 开头的错误代码才进行埋点
//                     noTracking: !String(rawResponse.status).startsWith('5')
//                   }
//                 )
//             }
//           } else {
//             options.silentError !== true &&
//               throwError(
//                 {
//                   data: transformContextToLog({
//                     request,
//                     response,
//                     options
//                   }),
//                   cause: {
//                     reason: 'onApiGatewayError',
//                     status: response.status
//                   },
//                   statusCode: response.status,
//                   message:
//                     t(`http.httpStatusErrorMsg.${response.status}`) ===
//                     `http.httpStatusErrorMsg.${response.status}`
//                       ? t('http.networkErrorMsg')
//                       : t(`http.httpStatusErrorMsg.${response.status}`)
//                 },
//                 {
//                   hideToast: options.silentError === 'HIDE_TOAST'
//                 }
//               )
//           }
//         }
//       } else {
//         if (import.meta.server && import.meta.dev) {
//           console.log(chalk.bgRed(`💡 << RESPONSE ${response.status}`))
//           console.log(
//             chalk.bgRed('ERROR'),
//             chalk.bgWhite.black(stringify(response._data))
//           )
//           console.timeEnd(chalk.gray(`${path} #${devRequestId} TIME`))
//         }
//         if (import.meta.client) {
//           if (response.status === 401 || response.status === 403) {
//             // 如果返回 HTTP 401/403 则弹出登录弹窗
//             showAuthErrorModal('token')
//           }
//         }
//         options.silentError !== true &&
//           throwError(
//             {
//               data: transformContextToLog({
//                 request,
//                 response,
//                 options
//               }),
//               cause: {
//                 reason: 'onNetworkError',
//                 status: response.status
//               },
//               statusCode: response.status,
//               message:
//                 t(`http.httpStatusErrorMsg.${response.status}`) ===
//                 `http.httpStatusErrorMsg.${response.status}`
//                   ? t('http.networkErrorMsg')
//                   : t(`http.httpStatusErrorMsg.${response.status}`)
//             },
//             {
//               hideToast: options.silentError === 'HIDE_TOAST'
//             }
//           )
//       }
//     },
//     onRequestError({ request, response, options: _options, error }) {
//       const options = _options as Parameters<typeof http>[0]
//       if (import.meta.server && import.meta.dev) {
//         console.log(chalk.bgRed(`💡 << RESPONSE ${response?.status}`))
//         console.log(chalk.bgRed('ERROR'), chalk.bgWhite.black(error?.message))
//         console.timeEnd(chalk.gray(`${path} #${devRequestId} TIME`))
//       }
//       options.silentError !== true &&
//         throwError(
//           {
//             data: transformContextToLog({
//               request,
//               response,
//               options,
//               error
//             }),
//             cause: {
//               reason: 'onRequestError',
//               status: response?.status
//             },
//             statusCode: response?.status,
//             message: t('http.networkErrorMsg')
//           },
//           {
//             hideToast: options.silentError === 'HIDE_TOAST'
//           }
//         )
//     },
//     onResponseError({ request, response, options: _options, error }) {
//       const options = _options as Parameters<typeof http>[0]
//       if (import.meta.server && import.meta.dev) {
//         console.log(chalk.bgRed(`💡 << RESPONSE ${response?.status}`))
//         console.log(chalk.bgRed('ERROR'), chalk.bgWhite.black(error?.message))
//         console.timeEnd(chalk.gray(`${path} #${devRequestId} TIME`))
//       }
//       options.silentError !== true &&
//         throwError(
//           {
//             data: transformContextToLog({
//               request,
//               response,
//               options,
//               error
//             }),
//             cause: {
//               reason: 'onResponseError',
//               status: response?.status
//             },
//             statusCode: response?.status,
//             message:
//               t(`http.httpStatusErrorMsg.${response?.status}`) ===
//               `http.httpStatusErrorMsg.${response?.status}`
//                 ? t('http.networkErrorMsg')
//                 : t(`http.httpStatusErrorMsg.${response?.status}`)
//           },
//           {
//             hideToast: options.silentError === 'HIDE_TOAST'
//           }
//         )
//     },
//     ...options
//   })
// }
